//
//  ZDNetworkTool.swift
//  1026SwiftSinaWeiBo
//
//  Created by Apple on 15/10/28.
//  Copyright © 2015年 itcast. All rights reserved.
//

import UIKit
import AFNetworking      //导入框架头文件

/**
    定义swift枚举
*/
enum ZDNetworkErrorType: Int {

    case EmptyAccessToken = -1
    case EmptyUid = -2
    
    //定义枚举属性 保存错误描述
    var description: String {
    
        get{
        
            switch self {
            
            case ZDNetworkErrorType.EmptyAccessToken:
                return "没有accessToken"
            case ZDNetworkErrorType.EmptyUid:
                return "没有uid"
            }
        }
    }
    
    //定义枚举方法
    func error() -> NSError {
    
        let error = NSError(domain: "cn.itcast.-026SwiftSinaWeiBo network error", code: rawValue, userInfo: ["description" : description])
        
        return error
    }
    
}


//MARK: - 网络单例继承AFN
class ZDNetworkTool: NSObject {
    
    //Mark: - swift创建单例
//    static let sharedNetworkTool = ZDNetworkTool()
    
    
    //创建单例对象
//    static let sharedInstance: ZDNetworkTool = {
//    
//        let baseURL = "https://api.weibo.com/"
//        
//        let tool = ZDNetworkTool(baseURL: NSURL(string: baseURL))
//        
//        return tool
//    }()
    
    //增加一个属性管理AFN
    private var afnManager: AFHTTPSessionManager
    
    //创建单例
    static let sharedInstance: ZDNetworkTool = ZDNetworkTool()
    
    //重写构造方法
    override init() {
        
        afnManager = AFHTTPSessionManager()
    }
    
    
    //申请应用时分配的AppKey
    let client_id = "2749501050"
    //授权回调地址，站外应用需与设置的回调地址一致
    let redirect_uri = "http://www.baidu.com/"
    //申请应用时分配的AppSecret
    let client_secret = "3005d538ba25dece299059cc2a0d84c0"
    
    
    /***  "https://api.weibo.com/oauth2/authorize?client_id=2749501050&redirect_uri=http://www.baidu.com/"  ***/
    //MARK: - 返回授权URL
    func authURL() -> NSURL {
    
        return NSURL(string: "https://api.weibo.com/oauth2/authorize?client_id=\(client_id)&redirect_uri=\(redirect_uri)")!
    }
    
    
    //MARK: - 请求accessToken
    func loadAccessToken(code: String, finished: ZDFinishedCallBack) {
        
    //https://api.weibo.com/oauth2/access_token
        
        let urlString = "https://api.weibo.com/oauth2/access_token"
        
        //定义请求参数字典
        let parameters = [
        
            "client_id" : client_id,    //申请应用时分配的AppKey
            "client_secret" : client_secret,  //申请应用时分配的AppSecret
            "grant_type" : "authorization_code",    //请求的类型，填写authorization_code
            "code" : code,         //调用authorize获得的code值
            "redirect_uri" : redirect_uri     //回调地址，需需与注册应用里的回调地址一致
        ]
        
        //增加解析类型
        afnManager.responseSerializer.acceptableContentTypes?.insert("text/plain")
        
        //测试响应结果
//        responseSerializer = AFHTTPResponseSerializer()
        
        afnManager.POST(urlString, parameters: parameters, success: { (_, result) -> Void in
            
            //请求成功
//            print("result = \(result)")
            
            //测试响应结果
//            let str = String(data: (result as! NSData), encoding: NSUTF8StringEncoding)
//            print(str)
            
            //调用回调闭包
            finished(result: result as? [String : AnyObject], error: nil)
            
            }) { (_, error: NSError) -> Void in
                
                //请求失败
//                print("error = \(error)")
                
                finished(result: nil, error: error)
        }
    }

    
    //MARK: - 加载用户信息
    func loadUserInfo(access_token: String?, uid: String?, finished: ZDFinishedCallBack) {
        
        //判断access_token 是否为空
        //守卫
        guard var parameters = getAccessToken(finished) else {
        
            return
        }
        
        //判断uid是否为空
        if uid == nil {
        
            //提示错误
            let networkError = ZDNetworkErrorType.EmptyUid   //定义枚举常量
            
            //调用回调
            finished(result: nil, error: networkError.error())
            
            return
        }
        
        let urlString = "https://api.weibo.com/2/users/show.json"
        
        //为字典添加元素
        parameters["uid"] = uid!
        
        //GET请求
//        afnManager.GET(urlString, parameters: parameters, success: { (_, result) -> Void in
//            
//            //请求成功回调闭包
//            finished(result: result as? [String : AnyObject], error: nil)
//            
//            }) { (_, error) -> Void in
//                
//                //请求失败回调闭包
//                finished(result: nil, error: error)
//        }
        
        self.GET(urlString, parameters: parameters, finished: finished)
    }
    
    //取别名 类似typedef
    typealias ZDFinishedCallBack = (result: [String : AnyObject]?, error: NSError?) -> Void
    
    //MARK: - 自己提供GET方法  进一步封装AFN  提高程序的可维护性
    func GET(URLString: String, parameters: AnyObject?, finished: ZDFinishedCallBack) {
    
        //调用AFN GET方法
        afnManager.GET(URLString, parameters: parameters, success: { (_, result) -> Void in
            
            //请求成功回调闭包
            finished(result: result as? [String : AnyObject], error: nil)
            
            }) { (_, error) -> Void in
                
                //请求失败回调闭包
                finished(result: nil, error: error)
        }
    }
    
    
    //MARK: - 抽取方法 获取accessToken
    private func getAccessToken(finished: ZDFinishedCallBack) -> [String : AnyObject]? {
    
        let access_token = ZDAccount.loadAccountData()?.access_token
        
        //判断access_token 是否为空
        if access_token == nil {
            
            //提示错误  自定义错误
            let networkError = ZDNetworkErrorType.EmptyAccessToken   //定义枚举常量
            
            //调用枚举方法
            let error = networkError.error()
            
            finished(result: nil, error: error)
            
            return nil
        }
        
        let parameters = ["access_token" : access_token!]
        
        return parameters
    }
    
    /*
        目前,每次刷新数据都是加载最新的20条数据,实际需要的效果是每次下拉刷新的数据都放到tableView的最前面
        新浪服务器返回的数据都是经过 微博id 排序的, 微博id大的表示离当前时间越近,排在数组的最上面
        微博的接口文档说明只传 access_token表示获取最新的 20条数据, since_id 表示 只返回id比since_id大的微博用于下拉刷新数据, max_id表示 只返回id小于或等于max_id的微博用于上拉加载更多数据
    
        微博内容从上到下 展示的依次是时间越来越早的微博，即最新的微博最先返回，存放在数组前面，展示在最上方。
        since_id 下拉刷新传入该参数。 越大表示微博的时间越新，越接近当前时间。下拉刷新的原理就是，传入当前最新微博的id给服务器，让服务器返回比当前微博时间更晚(更新)的微博，然后插入到当前微博模型数组的最开始处，重新刷新展示
    
        max_id：上拉加载传入该参数。 上拉加载的原理，传入当前展示的最后一条微博的id(更小)，让服务器返回比当前微博时间更早的微博，然后拼接到当前微博模型数组的后面，刷新展示
    */
    
    //MARK: - 加载微博数据模型  下拉刷新 上拉加载
    //since_id: 若指定此参数，则返回ID比since_id大的微博（即比since_id时间晚的微博），默认为0
    //max_id: 若指定此参数，则返回ID小于或等于max_id的微博，默认为0
    func loadStatuses(access_token: String?, since_id: Int, max_id: Int, finished: ZDFinishedCallBack) {
    
        //守卫 与 可选绑定刚好相反
        guard var parameters = getAccessToken(finished) else {
        
            //能够进来 说明返回值为nil  与 可选绑定刚好相反
            
            return
        }
        
        // https://api.weibo.com/2/statuses/home_timeline.json?access_token=2.00bNZZqBIpcEAD398458b44cAyjVZE
        
        let urlString = "https://api.weibo.com/2/statuses/home_timeline.json"
        
        
        if since_id > 0 {
        
            parameters["since_id"] = since_id
        }
        
        if max_id > 0 {
        
            //减1 避免加载出来的第一条数据重复  返回ID小于或等于max_id的微博
            parameters["max_id"] = max_id - 1
        }
        
//        print("parameters: \(parameters)");
        
        self.GET(urlString, parameters: parameters, finished: finished)
    }
    
    /**
     发布微博
     :param: image    发布微博所要上传的图片  新浪微博默认是最多可以上传9张，但是开发账号只能上传一张，所以这里要求一张图片
     :param: status   发布微博内容
     :param: finished 回调闭包
     */
    func sendStatus(image: UIImage?, status: String, finished: ZDFinishedCallBack) {
        
        //守卫 与 可选绑定刚好相反
        guard var parameters = getAccessToken(finished) else {
            
            //能够进来 说明返回值为nil  与 可选绑定刚好相反
            
            return
        }
        
        parameters["status"] = status
        
        if let im = image {   //发表带图片的微博
        
            //https://upload.api.weibo.com/2/statuses/upload.json
            let urlString = "https://upload.api.weibo.com/2/statuses/upload.json"
            
            afnManager.POST(urlString, parameters: parameters, constructingBodyWithBlock: { (formData) -> Void in
                
                let data = UIImagePNGRepresentation(im)!
                
                /**
                *  第一个参数：图片二进制
                   第二个参数：要上传的图片 由新浪微博api指定，不能更改
                   第三个参数：图片保存在服务器的名称，可以随意，由服务器端统一指定
                   第四个参数：图片格式
                */
                formData.appendPartWithFileData(data, name: "pic", fileName: "", mimeType: "image/png")
                
                }, success: { (_, result) -> Void in
                    
                    finished(result: result as? [String: AnyObject], error: nil)
                    
                }, failure: { (_, error) -> Void in
                    
                    finished(result: nil, error: error)
            })
            
        }else {    //发送不带图片的微博
        
            // https://api.weibo.com/2/statuses/update.json
            let urlString = "https://api.weibo.com/2/statuses/update.json"
            
            afnManager.POST(urlString, parameters: parameters, success: { (_, result) -> Void in
                
                finished(result: result as? [String : AnyObject], error: nil)
                
                }) { (_, error) -> Void in
                    
                    finished(result: nil, error: error)
            }

        }
    }
}
